package com.echovin.esb.gateway.filter;

import com.echovin.esb.gateway.constants.ErrorCode;
import com.echovin.esb.gateway.constants.OrderConstants;
import com.echovin.esb.gateway.exception.OpenException;
import com.echovin.esb.gateway.locator.GatewayParameterValidateResourceLocator;
import com.echovin.esb.gateway.model.TwoTuple;
import com.echovin.esb.gateway.parameter.SchemaValidator;
import com.echovin.esb.gateway.parameter.impl.JsonSchemaValidator;
import com.echovin.esb.gateway.parameter.impl.XMLSchemaValidator;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.OrderedGatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;

import java.net.URI;
import java.util.*;

/**
 * 服务编排过滤器
 */
@Slf4j
//@Component
public class ParameterValidateGatewayFilterFactory extends AbstractGatewayFilterFactory<ParameterValidateGatewayFilterFactory.Config> {
    private static final String DATETIME_KEY = "enable";
    public static final String CACHE_REQUEST_BODY_OBJECT_KEY = "cachedRequestBodyObject";
    @Autowired
    GatewayParameterValidateResourceLocator validateResourceLocator;

    public ParameterValidateGatewayFilterFactory() {
        super(ParameterValidateGatewayFilterFactory.Config.class);
    }

    @Override
    public List<String> shortcutFieldOrder() {
        return Collections.singletonList(DATETIME_KEY);
    }


    @Override
    public GatewayFilter apply(ParameterValidateGatewayFilterFactory.Config config) {
        return new OrderedGatewayFilter((exchange, chain) -> {
            // 读取cacheBodyFilter中缓存中的body
            String cachedBody = exchange.getAttribute(CACHE_REQUEST_BODY_OBJECT_KEY);
            if (cachedBody == null) {
                return chain.filter(exchange);
            }
            ServerHttpRequest request = exchange.getRequest();
            URI requestUri = request.getURI();
            HttpHeaders headers = request.getHeaders();
            MediaType contentType = headers.getContentType();
            // 只处理 application/xml、application/json 格式参数
            SchemaValidator validator;
            if (MediaType.APPLICATION_JSON.equals(contentType)) {
                validator = new JsonSchemaValidator(validateResourceLocator);
            } else if (MediaType.APPLICATION_XML.equals(contentType)) {
                validator = new XMLSchemaValidator(validateResourceLocator);
            } else {
                return chain.filter(exchange);
            }
            String url = request.getURI().getPath();
            if (!StringUtils.isEmpty(headers.getFirst("SOAPAction"))) {
                // 说明是webservice，对其动作进行参数校验
                url = headers.getFirst("SOAPAction");
            }
            // 根据scheme校验body
            TwoTuple<Boolean, String> twoTuple = validator.schemaValidator(url, cachedBody);
            if (twoTuple != null && !twoTuple.first) {
                throw new OpenException(ErrorCode.PARAMWTER_ERROR.getCode(),twoTuple.second);
            }

            return chain.filter(exchange);

        }, OrderConstants.PARAMTER_CHECK);
    }

    public static class Config {
        /**
         * 使能 key
         */
        private boolean enable;

        public boolean isEnable() {
            return enable;
        }

        public void setEnable(boolean enable) {
            this.enable = enable;
        }
    }

}
